# 还是用原来的方法吧
from flask import *
# 导入数据库部分
from database import TodoDB
# 数据格式
from data import Todo
# 用于处理异常的库
import traceback

app = Flask(__name__)
host = "0.0.0.0"
port = 80
# 数据库初始化
db = TodoDB()


@app.route('/')
def index():
    # 在这里加载了一个模板
    # 在加载模板的时候可以传入参数
    # 参数可以是几乎任何类型
    # 可以用这种方法在页面生成的过程中给用户传递消息
    # 在HTML文件中使用参数是{{ 参数名 }}的方法。（空格可以不用
    # 在HTML中写一些代码也是可行的
    # 在{% %}中写控制代码
    return render_template('index.html')


# 这是用作资源转发
# 对 `/***/...` 的请求转发到 `/static/***/...`
# `/static/...` 是Flask的默认静态文件目录，访问这里就能直接下载文件
@app.route('/<path:path_name>')
def static_files(path_name: str):
    return redirect('/static/%s' % path_name)


# 下面是API内容了
class Errors:
    OK = 0
    NOT_FOUND = 1
    FORMAT = 2
    UNKNOWN = 100
    messages = {
        OK: "Success",
        NOT_FOUND: "Data not found",
        FORMAT: "Data format error",
        UNKNOWN: "Unknown error"
    }


# 定义RESTful格式的返回值
def make_result(code=Errors.OK, data=None, message=Errors.messages[Errors.OK]):
    result = {
        'code': code,
        'message': message
    }
    if data is not None:
        result['data'] = data
    if not code == Errors.OK:
        try:
            message = Errors.messages[code]
        except KeyError:
            message = Errors.messages[Errors.UNKNOWN]
        result['message'] = message
    return result


# 返回自定义的异常格式
@app.errorhandler(Exception)
def error_handler_500(error):
    traceback.print_exc()
    return make_result(500, message="Caught Exception: %s" % traceback.format_exc()), 500


@app.errorhandler(404)
def error_handler_404(error):
    return make_result(404, message="%s" % str(error)), 404


api_vi = '/api/v1/'


# 获取所有的item
@app.route(api_vi + "fetch/")
def fetch_list():
    return make_result(0, list(map(lambda x: x.to_json(), db.get())))


# 获取单条
@app.route(api_vi + "fetch/<int:tid>")
def fetch_by_tid(tid: int):
    return db.get_by_tid(tid).to_json()


# 插入一条新的
@app.route(api_vi + 'submit', methods=['GET', 'POST'])
def submit():
    try:
        js = request.get_json(force=True)
        if not js:
            raise ValueError
    except ValueError:
        return make_result(Errors.FORMAT)
    # print(js)
    todo = Todo.from_json_static(js)
    db.insert(todo)
    return make_result(0)


# 更新一条
# 上传的信息会更新，未定义的就不会更新
# methods提供允许的访问方法
@app.route(api_vi + 'update/<int:tid>', methods=['GET', 'POST'])
def update_one(tid: int):
    todo = db.get_by_tid(tid)
    if not todo:
        return make_result(Errors.NOT_FOUND)
    todo_js = todo.to_json()
    try:
        js = request.get_json(force=True)
        if not js:
            raise ValueError
    except ValueError:
        return make_result(Errors.FORMAT)
    # print(js)
    # 仅更新指定部分
    try:
        for key in js:
            if js[key] is None:
                continue
            todo_js[key] = js[key]
    except KeyError:
        return make_result(Errors.FORMAT)
    if not db.update(Todo.from_json_static(todo_js)):
        return make_result(Errors.UNKNOWN)
    return make_result(0)


if __name__ == '__main__':
    app.run(host, port, debug=False)
